﻿using System;
using System.Collections.Generic;
using ValidationFramework.Reflection;

namespace ValidationFramework.Web.MVC
{
	/// <summary>
	/// Will extract all client-side enabled rules for the given type
	/// </summary>
	/// <remarks>By default, rules will be placed</remarks>
	public class TypeExtractionStrategy : IRuleExtractionStrategy
	{
	    readonly Type modelType;
	    readonly string propertyList;
	    readonly bool isWhiteList;

		/// <summary>
		/// Initializes a new instance of the <see cref="TypeExtractionStrategy"/> class.
		/// </summary>
		public TypeExtractionStrategy(Type modelType) : this(modelType, string.Empty, false)
		{
		}
		public TypeExtractionStrategy(Type modelType, string propertyList) : this(modelType, propertyList, false)
		{
		}
		public TypeExtractionStrategy(Type modelType, string propertyList, bool isWhiteList)
		{
			this.modelType = modelType;
			this.propertyList = propertyList;
			this.isWhiteList = isWhiteList;
		}


		#region IRuleExtractionStrategy Members

		public IList<PropertyRuleInfo> GetRules()
		{
			//TODO: refactor out globals: 'TypeCache'.
			var validatedType = TypeCache.GetType(modelType.TypeHandle);
			var rules = new List<PropertyRuleInfo>();
			foreach (var property in validatedType.Properties)
			{
				if (!IsVIP(property))
				{
                    continue; // skip this property 
                }

				foreach (var rule in property.Rules)
				{
					rules.Add(new PropertyRuleInfo()
					              {
					                  Rule = rule, 
                                      PropertyName = property.Name, 
                                      Type = modelType
					              });
				}
			}
			return rules;
		}

		#endregion

		private bool IsVIP(InfoDescriptor property)
		{
			if (string.IsNullOrEmpty(propertyList))
            {
                return true; // by default all properties are allowed
            }
			if (isWhiteList)
			{
			    return propertyList.Contains(property.Name);
			}
			else
            {
                return !propertyList.Contains(property.Name); // blacklist the property
            }
		}
	}
}
